package com.aps.server.controller;

import com.alibaba.fastjson2.JSON;
import com.aps.algorithm.core.APSAlgorithm;
import com.aps.algorithm.core.AlgorithmParameters;
import com.aps.algorithm.entity.BasicEquipSchedulingResult;
import com.aps.algorithm.heuristic.GeneticAlgorithm;
import com.aps.algorithm.heuristic.genetic.dto.ApsOperationDto;
import com.aps.algorithm.heuristic.genetic.model.Chromosome;
import com.aps.common.boot.CoreApplicationContext;
import com.aps.common.constant.Constants;
import com.aps.common.entity.Result;
import com.aps.common.exception.SchedulingInvalidateException;
import com.aps.common.model.ApsParameterModel;
import com.aps.common.model.SchedulingResult;
import com.aps.common.model.genetic.ProcessInterval;
import com.aps.server.context.ValidateContext;
import com.aps.server.dto.SchedulingPlanGenerateDto;
import com.aps.server.entity.ApsOrder;
import com.aps.server.entity.BasicEquip;
import com.aps.server.mapper.ApsOrderMapper;
import com.aps.server.service.ApsConstraintService;
import com.aps.server.service.ApsSchedulingResultService;
import com.aps.server.service.SchedulingPlanService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 排程方案生成控制器
 * 处理排程方案的生成、查询等操作
 *
 * @author APS System
 * @date 2025-10-13
 */
@Slf4j
@RestController
@RequestMapping("/api/scheduling-plan")
@Tag(name = "排程方案管理", description = "排程方案生成与管理接口")
public class SchedulingPlanController {

    @Resource
    ApsConstraintService apsConstraintService;
    @Resource
    SchedulingPlanService service;


    /**
     * 生成排程方案
     * 接收前端提交的完整配置数据，生成排程方案
     *
     * @param dto 排程方案生成请求DTO
     * @return 排程方案生成结果
     */
    @PostMapping("/generate")
    @Operation(summary = "生成排程方案", description = "根据提交的配置数据生成排程方案")
    public Result<?> generateSchedulingPlan(@RequestBody List<SchedulingPlanGenerateDto> dtos) {
        if(CollectionUtils.isEmpty(dtos)){
            return Result.error(499,"未获取到约束数据",
                    null,"服务异常");
        }
        //先校验参数
        Map<String,ApsParameterModel> modelMap = new HashMap<>();
        Map<String,Map<String, Object>> paramMap = new HashMap<>();
        for (SchedulingPlanGenerateDto dto : dtos) {
            //修改约束内容 ，从缓存中获取
            SchedulingPlanGenerateDto cacheInfo
                    =  apsConstraintService.getTenantIdMapCacheInfo(dto.getBaseParameters().getConstraintInfo().getId());
            //订单内容、还是从界面中获取
            cacheInfo.setGenerateTime(dto.getGenerateTime());
            cacheInfo.setSelectedOrderIds(dto.getSelectedOrderIds());
            cacheInfo.setOrderCount(dto.getOrderCount());
            log.info("接收到排程方案生成请求");
            log.info("约束配置: {}", cacheInfo.getBaseParameters().getConstraintInfo().getTitle());
            log.info("选中工单数量: {}", cacheInfo.getOrderCount());
            log.info("设备配置数量: {}", cacheInfo.getDeviceConfiguration() != null ? cacheInfo.getDeviceConfiguration().size() : 0);

            // 打印详细的请求数据（调试用）
            logRequestDetails(cacheInfo);
            List<String> orderCodes = cacheInfo.getSelectedOrderIds()
                    .stream().map(SchedulingPlanGenerateDto.SelectedOrderDto::getApsOrderCode).toList();
            List<ApsOrder> apsOrders = service.getApsOrders(orderCodes);
            if(CollectionUtils.isEmpty(apsOrders)){
                return Result.error("数据库中未查询到当前订单编号相关数据");
            }
            List<String> equipCodes = cacheInfo.getDeviceConfiguration()
                    .stream().map(SchedulingPlanGenerateDto.DeviceConfigDto::getEquipCode).distinct().toList();
            List<BasicEquip> equipts = service.getBasicEquips(equipCodes);
            ValidateContext context = new ValidateContext();
            context.setOrders(apsOrders);
            context.setEquips(equipts);
            String configId = dto.getBaseParameters().getConstraintInfo().getId();
            try {
                // TODO: 基于订单数据校验参数配置
                service.validateBaiscData(context);
                // TODO: 构造算法业务数据
                ApsParameterModel apsParameterModel = service.buildAlgorthmsBusinessParameters(cacheInfo, context);
                // TODO: 构造算法配置  + 约束配置
                Map<String, Object> parameters = service.algorthmsBasicParameters(cacheInfo);
                modelMap.put(configId, apsParameterModel);
                paramMap.put(configId,parameters);
            }
            catch (Exception e) {
                String title = dto.getBaseParameters().getConstraintInfo().getTitle();
                //Code 499 前端弹出对应 提示框
                if(e instanceof SchedulingInvalidateException){
                    SchedulingInvalidateException ex = (SchedulingInvalidateException) e;
                    return Result.error(499,"【约束：" + title + "】 \n" + ex.getMessage(),
                            ex.getData(),"生成排程方案，校验未通过");
                }
                log.error("生成排程方案失败 约束规则名称：{} ， 失败详情：{}", title, e.getMessage());

                return Result.error(499,"【约束：" + title + "】生成排程方案失败，详情如下： "
                        , e.getMessage() , "方案生成失败");
            }
        }
        //调用算法
        Map<SchedulingPlanGenerateDto,Chromosome<ApsOperationDto>> chromosomes = new HashMap<>();
        for (SchedulingPlanGenerateDto dto : dtos){
            String configId = dto.getBaseParameters().getConstraintInfo().getId();
            try {
                // TODO: 选用算法
                APSAlgorithm algorithm = (GeneticAlgorithm) CoreApplicationContext.getApplicationContext().getBean("geneticAlgorithm");
                // TODO: BUILD
                AlgorithmParameters algorithmParameters = AlgorithmParameters.builder()
                        .enableDetailedLogging(true)
                        .parameters(paramMap.get(configId))
                        .build();
                // TODO: 调用算法引擎执行排程计算
                Chromosome<ApsOperationDto> execute = algorithm.execute(modelMap.get(configId), algorithmParameters);
                chromosomes.put(dto, execute);
            } catch (Exception e){
                String title = dto.getBaseParameters().getConstraintInfo().getTitle();
                log.error("算法执行失败 cause:{}", e.getMessage());
                return Result.error(499,"【约束：" + title + "】算法调用失败，详情如下： "
                        , e.getMessage() , "算法调用失败");
            }
        }
        //全部校验成功后，统一缓存 void
        chromosomes.forEach((key, value) -> {
            String cId = key.getBaseParameters().getConstraintInfo().getId();
            String cName = key.getBaseParameters().getConstraintInfo().getTitle();
            //TODO: 构造算法返回结构
            List<BasicEquipSchedulingResult> resultList = service.buildAlgorthmsResultList(value, cId, cName);
            //TODO: 根据算法得出的排期值，计算相关kpi指标
//            service.calKPI(resultList);

            // TODO: 缓存参数配置
            service.setCacheConfigerations(key);
            // TODO: 缓存结果
            service.cacheSchedulingResults(resultList, cId);
        });
        // 临时返回成功响应
        return Result.success("排程方案生成成功", null);
    }

    /**
     * 打印请求详细信息（用于调试）
     */
    private void logRequestDetails(SchedulingPlanGenerateDto dto) {
        log.debug("========== 排程方案生成请求详情  ==========" +
                "【" + dto.getBaseParameters().getConstraintInfo().getTitle() + "】");
        
        // 基础参数
        if (dto.getBaseParameters() != null) {
            log.debug("【基础参数】");
            log.debug("  - 开始日期: {}", dto.getBaseParameters().getStartDate());
            log.debug("  - 加班优先: {}", dto.getBaseParameters().getWorkOverTime());
            log.debug("  - 约束配置: {}", dto.getBaseParameters().getConstraintInfo().getTitle());
            
            // 权重配置
            log.debug("【权重配置】");
            if (Boolean.TRUE.equals(dto.getBaseParameters().getEnableChangeLaneRate())) {
                log.debug("  - 换线次数权重: {}%", dto.getBaseParameters().getChangeLaneRate());
            }
            if (Boolean.TRUE.equals(dto.getBaseParameters().getEnableDeliveryRate())) {
                log.debug("  - 交期权重: {}%", dto.getBaseParameters().getDeliveryRate());
            }
            if (Boolean.TRUE.equals(dto.getBaseParameters().getEnableEquiptUseProbabilityRate())) {
                log.debug("  - 设备利用率权重: {}%", dto.getBaseParameters().getEquiptUseProbabilityRate());
            }
        }
        
        // 工作时间配置
        if (dto.getWorkTimeConfiguration() != null && !dto.getWorkTimeConfiguration().isEmpty()) {
            log.debug("【工作时间配置】");
            dto.getWorkTimeConfiguration().forEach(workTime -> {
                log.debug("  - {}: 生产时段{}个, 加班时段{}", 
                    workTime.getDayName(),
                    workTime.getWorkPeriods() != null ? workTime.getWorkPeriods().size() : 0,
                    workTime.getOvertimePeriod() != null ? "1个" : "无");
            });
        }
        
        // 设备配置
        if (dto.getDeviceConfiguration() != null && !dto.getDeviceConfiguration().isEmpty()) {
            log.debug("【设备配置】");
            dto.getDeviceConfiguration().forEach(device -> {
                log.debug("  - {}: 类型={}, 数量={}, 维护计划{}个",
                    device.getEquipName(),
                    device.getEquipType(),
                    device.getQuantity(),
                    device.getMaintenancePlans() != null ? device.getMaintenancePlans().size() : 0);
            });
        }
        
        // 工单信息
        if (dto.getSelectedOrderIds() != null && !dto.getSelectedOrderIds().isEmpty()) {
            log.debug("【选中工单】");
            log.debug("  - 工单总数: {}", dto.getSelectedOrderIds().size());
            dto.getSelectedOrderIds().forEach(order -> {
                log.debug("    * {}: 产品={}", order.getOrderCode(), order.getProductCode());
            });
        }
        
        log.debug("=========================================");
    }

    /**
     * 查询排程方案列表
     *
     * @return 排程方案列表
     */
    @GetMapping("/list")
    @Operation(summary = "查询排程方案列表", description = "获取所有排程方案列表")
    public Result<?> listSchedulingPlans() {
        log.info("查询排程方案列表");
        // TODO: 实现查询逻辑
        return Result.success("查询成功", null);
    }

    /**
     * 查询排程方案详情
     *
     * @param planId 方案ID
     * @return 排程方案详情
     */
    @GetMapping("/{planId}")
    @Operation(summary = "查询排程方案详情", description = "根据方案ID查询详细信息")
    public Result<?> getSchedulingPlan(@PathVariable String planId) {
        log.info("查询排程方案详情, planId: {}", planId);
        // TODO: 实现查询逻辑
        return Result.success("查询成功", null);
    }

    /**
     * 删除排程方案
     *
     * @param planId 方案ID
     * @return 删除结果
     */
    @DeleteMapping("/{planId}")
    @Operation(summary = "删除排程方案", description = "根据方案ID删除排程方案")
    public Result<?> deleteSchedulingPlan(@PathVariable String planId) {
        log.info("删除排程方案, planId: {}", planId);
        // TODO: 实现删除逻辑
        return Result.success("删除成功", null);
    }
}

